package cn.tedu._03vehicle.base.interceptors;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
import java.util.concurrent.ConcurrentHashMap;

//限流拦截器
@Slf4j
public class RateLimitInterceptor implements HandlerInterceptor {
        /*
        1.先获取访问时间   现在的时间>最后一次访问时间+60秒   ，则重新计数
        先获取访问时间   现在的时间<最后一次访问时间+60秒   计数+1
         */
    private static final int MAX_REQUEST_PER_MINUTE = 3;  // 每分钟最大请求次数
    private static final int WINDOW_SIZE_SECONDS = 60;  // 时间窗口大小（秒）
    private final ConcurrentHashMap<String,Integer> clientCounts = new ConcurrentHashMap<>();    // 存储每个客户端的请求计数
    private final ConcurrentHashMap<String, LocalDateTime> clientTimes = new ConcurrentHashMap<>();  // 存储每个客户端的最后访问时间

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    //1.获取客户端的IP地址
        String addr = request.getRemoteAddr();
        //2.获取并判断时间
        LocalDateTime lastTime = clientTimes.get(addr);
        if(lastTime == null || LocalDateTime.now().isAfter(lastTime.plusSeconds(WINDOW_SIZE_SECONDS))){
            //1.计数器清零；
            clientCounts.put(addr,0);
            //2.记录访问时间
            clientTimes.put(addr,LocalDateTime.now());
        }
        //计数器+1
        Integer count = clientCounts.merge(addr,1,Integer::sum);
        //判断是否超过3
        if(count>MAX_REQUEST_PER_MINUTE){
            log.warn("客户端{}访问过于频繁，请稍后再试",addr);
            response.setStatus(429);
            throw new RuntimeException("客户端访问过于频繁，请稍后再试");
        }
        return true;
    }
}
